/**
 * request.js
 * 基础请求文件
 */
// token使用
import {
	getToken
} from "../token.js";
// #ifdef MP-WEIXIN
// 微信的实时日志
import log from "../wx_log/wx_log.js";
// #endif
// 默认配置
const defaultConfig = {
	// 请求配置
	baseURL: "", // 请求的 baseURL（域名地址）
	url: "", // 接口地址
	data: {}, // 请求的参数
	method: "POST", // HTTP 请求方法
	header: {
		"content-type": "application/json", // 默认值
	}, // 设置请求的 header，header 中不能设置 Referer。content-type 默认为 application/json
	timeout: 60000, // 超时时间，默认60秒，单位为毫秒
	// 其他配置
	debug: true, // 是否开启打印调试
	alert_time_duration: 1000, // 弹框显示时间
	alert_timeout: true, // 请求超时弹框
	alert_timeout_text: "网络繁忙，请稍后再试！", // 请求超时弹框提示内容
	alert_error: true, // 请求失败弹框
	alert_error_text: "", // 请求失败弹框提示内容
};
// request
const wRequest = (params) => {
	// 引用实例
	const app = getApp();
	defaultConfig.baseURL = app.globalData.wReqUrl; // 请求的 baseURL（域名地址）

	return new Promise((resolve, reject) => {
		(params && Object.prototype.toString.call(params) === "[object Object]") ||
		(params = {}); // 判断参数是否是对象
		const config = {
			...defaultConfig,
			...params,
		};
		// 开发者服务器接口地址(tip：注意是baseURL和path的拼接)
		if (!config.url) {
			config.url = `${config.baseURL}${config.path}`;
		}
		// 接口调用成功的回调函数
		if (Object.prototype.toString.call(config.success) != "[object Function]") {
			config.success = (res) => {
				if (res.statusCode == 200) {
					// 返回值
					let resData = res.data;
					// 调试
					if (config.debug) {
						console.log("接口:", config.path, "请求结果:", resData);
					}

					// 服务器返回的code编码，例:000000-正确
					if (resData.code == "000000") {
						// #ifdef MP-WEIXIN
						// 实时日志
						log.info(
							`接口请求——接口:${config.path},参数:${JSON.stringify(
                config.data
              )},结果:${JSON.stringify(resData)}`
						);
						// #endif
						resolve(resData);
					} else {
						// #ifdef MP-WEIXIN
						// 实时日志
						log.error(
							`接口请求——接口:${config.path},参数:${JSON.stringify(
                config.data
              )},结果:${JSON.stringify(resData)}`
						);
						// #endif

						// 根据指定错误code码做相应的操作(与后端沟通好)
						// 示例-100001错误
						if (resData.code == "100001") {
							// 执行特定操作
							reject(resData);
						}

						// 提示弹框
						if (config.alert_error) {
							uni.showToast({
								title: `${
                  config.alert_error_text
                    ? config.alert_error_text
                    : resData.msg
                }`,
								icon: "none",
								mask: true,
								duration: config.alert_time_duration,
							});
						}
						reject(resData);
					}
				} else {
					// #ifdef MP-WEIXIN
					// 实时日志
					log.error(
						`接口请求——接口:${config.path},参数:${JSON.stringify(
              config.data
            )},结果:${JSON.stringify(res)}`
					);
					// #endif
					// 调试
					console.error("接口:", config.path, "错误:", res);
					reject(res);
				}
			};
		}
		// 接口调用失败的回调函数
		if (Object.prototype.toString.call(config.fail) != "[object Function]") {
			config.fail = (err) => {
				// #ifdef MP-WEIXIN
				// 实时日志
				log.error(
					`接口请求——接口:${config.path},参数:${JSON.stringify(
            config.data
          )},结果:${JSON.stringify(err)}`
				);
				// #endif
				// 调试
				console.log("接口:", config.path, "错误:", err);
				if (config.alert_timeout && err.errMsg == "request:fail timeout") {
					uni.showToast({
						title: config.alert_timeout_text,
						icon: "none",
						mask: true,
					});
				}
				reject(err);
			};
		}
		// 接口调用结束的回调函数（调用成功、失败都会执行）
		if (
			Object.prototype.toString.call(config.complete) != "[object Function]"
		) {
			config.complete = (result) => {};
		}

		// 是否需要设置 token
		const isToken = (config.header || {})?.isToken === false;
		// 添加 token
		if (!isToken && getToken()) {
			config.header["Authorization"] = "Bearer " + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
		}
		// 是否需要防止数据重复提交
		const isRepeatSubmit = (config.header || {})?.repeatSubmit === false;
		const isRepeatSubmit_time = (config.header || {})?.repeatSubmitTime || 1000;
		// 添加请求参数(防止数据重复提交)(简易版-单线程网络请求)
		if (!isRepeatSubmit) {
			const requestObj = {
				url: config.url,
				data: typeof config.data === "object" ?
					JSON.stringify(config.data) : config.data,
				time: new Date().getTime(),
			};
			const storageObj = uni.getStorageSync("storageObj");
			if (
				storageObj === undefined ||
				storageObj === null ||
				storageObj === ""
			) {
				uni.setStorageSync("storageObj", JSON.stringify(requestObj)); // 转换为JSON字符串缓存
			} else {
				storageObj = JSON.parse(storageObj); // 转换为JSON对象
				const s_url = storageObj.url; // 请求地址
				const s_data = storageObj.data; // 请求数据
				const s_time = storageObj.time; // 请求时间
				const interval = isRepeatSubmit_time; // 间隔时间(ms)，小于此时间视为重复提交
				if (
					s_data === requestObj.data &&
					requestObj.time - s_time < interval &&
					s_url === requestObj.url
				) {
					const message = "数据正在处理，请勿重复提交";
					console.warn(`[${s_url}]: ` + message);
					uni.showToast({
						title: message,
						icon: "none",
						mask: true,
					});
					reject(message);
				} else {
					uni.setStorageSync("storageObj", JSON.stringify(requestObj)); // 转换为JSON字符串缓存
				}
			}
		}
		// 调试
		if (config.debug) {
			console.log("请求配置文件：", config);
			console.log("接口:", config.path, "请求参数:", config.data);
		}
		// 发起 HTTPS 网络请求
		uni.request(config);
	});
};
// get
const wGet = (url, params) => {
	(params && Object.prototype.toString.call(params) === "[object Object]") ||
	(params = {}); // 判断参数是否是对象
	params.path = url;
	params.method = "GET";
	return wRequest(params);
};
// post
const wPost = (url, params) => {
	(params && Object.prototype.toString.call(params) === "[object Object]") ||
	(params = {}); // 判断参数是否是对象
	params.path = url;
	params.method = "POST";
	return wRequest(params);
};
// options
const wOptions = (url, params) => {
	(params && Object.prototype.toString.call(params) === "[object Object]") ||
	(params = {}); // 判断参数是否是对象
	params.path = url;
	params.method = "OPTIONS";
	return wRequest(params);
};
// head
const wHead = (url, params) => {
	(params && Object.prototype.toString.call(params) === "[object Object]") ||
	(params = {}); // 判断参数是否是对象
	params.path = url;
	params.method = "HEAD";
	return wRequest(params);
};
// put
const wPut = (url, params) => {
	(params && Object.prototype.toString.call(params) === "[object Object]") ||
	(params = {}); // 判断参数是否是对象
	params.path = url;
	params.method = "PUT";
	return wRequest(params);
};
// delete
const wDelete = (url, params) => {
	(params && Object.prototype.toString.call(params) === "[object Object]") ||
	(params = {}); // 判断参数是否是对象
	params.path = url;
	params.method = "DELETE";
	return wRequest(params);
};
// trace
const wTrace = (url, params) => {
	(params && Object.prototype.toString.call(params) === "[object Object]") ||
	(params = {}); // 判断参数是否是对象
	params.path = url;
	params.method = "TRACE";
	return wRequest(params);
};
// connect
const wConnect = (url, params) => {
	(params && Object.prototype.toString.call(params) === "[object Object]") ||
	(params = {}); // 判断参数是否是对象
	params.path = url;
	params.method = "CONNECT";
	return wRequest(params);
};

export default {
	request: wRequest,
	get: wGet,
	post: wPost,
	options: wOptions,
	head: wHead,
	put: wPut,
	delete: wDelete,
	trace: wTrace,
	connect: wConnect,
};